/*
* Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. 
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include <cerrno>
#include <dlfcn.h>

#include "utils/log/infer_log.h"
#include "infer_framework_factory.h"
#include "paddlelite_wrapper.h"
#include "ncnn_wrapper.h"
#include "mnn_wrapper.h"

InferFramework *InferFrameworkFactory::Create(AlgorithmInfo &algoConfig)
{
    void *inferWrapper = nullptr;
    switch (algoConfig.frameworkType)
    {
    #ifdef INFER_WITH_PADDLELITE
    case Framework_type::AI_FRAMEWORK_ID_PADDLELITE:
    {
        PaddleliteWrapper *pdWrapper = new (std::nothrow) PaddleliteWrapper;
        if (pdWrapper == nullptr)
        {
            HILOGE("new PaddleliteWrapper fail");
            return nullptr;
        }

        AiRetCode rnt = pdWrapper->Init(algoConfig);
        if (rnt != AiRetCode::AI_RETCODE_SUCCESS)
        {
            HILOGE("PaddleliteWrapper init fail");
            delete pdWrapper;
            pdWrapper = nullptr;
            return nullptr;
        }

        inferWrapper = static_cast<void *>(pdWrapper);
        break;
    }
    #endif
    #ifdef INFER_WITH_NCNN
    case Framework_type::AI_FRAMEWORK_ID_NCNN:
    {
        NcnnWrapper *ncnnWrapper = new (std::nothrow) NcnnWrapper;
        if (ncnnWrapper == nullptr)
        {
            HILOGE("new NcnnWrapper fail");
            return nullptr;
        }

        AiRetCode rnt = ncnnWrapper->Init(algoConfig);
        if (rnt != AiRetCode::AI_RETCODE_SUCCESS)
        {
            HILOGE("NcnnWrapper init fail");
            delete ncnnWrapper;
            ncnnWrapper = nullptr;
            return nullptr;
        }

        inferWrapper = static_cast<void *>(ncnnWrapper);
        break;
    }
    #endif
    #ifdef INFER_WITH_MNN
    case Framework_type::AI_FRAMEWORK_ID_MNN:
    {
        MnnWrapper *mnnWrapper = new (std::nothrow) MnnWrapper;
        if (mnnWrapper == nullptr)
        {
            HILOGE("new PaddleliteWrapper fail");
            return nullptr;
        }

        AiRetCode rnt = mnnWrapper->Init(algoConfig);
        if (rnt != AiRetCode::AI_RETCODE_SUCCESS)
        {
            HILOGE("PaddleliteWrapper init fail");
            delete mnnWrapper;
            mnnWrapper = nullptr;
            return nullptr;
        }

        inferWrapper = static_cast<void *>(mnnWrapper);
        break;
    }
    #endif
    default:
    {
        HILOGE("Unknown framework type");
        return nullptr;
    }
    }
    if (inferWrapper == nullptr)
    {
        HILOGE("Failed to create inferwrapper.");
        return nullptr;
    }
    return reinterpret_cast<InferFramework *>(inferWrapper);
}
